//   Copyright 2012,2013 Vaughn Vernon
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package com.saasovation.agilepm.domain.model.team;

import java.util.Date;

import com.saasovation.agilepm.domain.model.Entity;
import com.saasovation.agilepm.domain.model.tenant.TenantId;

/**
 * @实体：成员
 * @author learn
 */
public abstract class Member extends Entity {

    /**
     * 成员改变追踪器
     */
    private MemberChangeTracker changeTracker;

    /**
     * 邮件地址
     */
    private String emailAddress;
    /**
     * 已启用
     */
    private boolean enabled = true;
    /**
     * 名字
     */
    private String firstName;
    /**
     * 姓氏
     */
    private String lastName;
    /**
     * 租户编号
     */
    private TenantId tenantId;
    /**
     * 用户名
     */
    private String username;

    /**
     * 由以下参数构造成员
     * @param aTenantId 		租户编号
     * @param aUsername 		用户名
     * @param aFirstName		名字
     * @param aLastName			姓氏
     * @param anEmailAddress	邮件地址
     * @param anInitializedOn	初始日期
     */
    public Member(
            TenantId aTenantId,
            String aUsername,
            String aFirstName,
            String aLastName,
            String anEmailAddress,
            Date anInitializedOn) {
        // 刨除初始化于日期，调用保护构造器
        this(aTenantId, aUsername, aFirstName, aLastName, anEmailAddress);

        // 设置改变追踪器
        this.setChangeTracker(
                new MemberChangeTracker(
                        anInitializedOn,
                        anInitializedOn,
                        anInitializedOn));
    }

    /**
     * 改变邮件地址
     * @param anEmailAddress 邮件地址
     * @param asOfDate		 截至日期
     */
    public void changeEmailAddress(String anEmailAddress, Date asOfDate) {
        // 如果追踪器的可以改变邮件地址 并且 当前邮件地址不等于 参数邮件地址；则改变；否则不改变
        if (this.changeTracker().canChangeEmailAddress(asOfDate) &&
                !this.emailAddress().equals(anEmailAddress)) {
            // 设置邮件地址
            this.setEmailAddress(anEmailAddress);
            // 由截至日期，重置追踪器的邮件地址
            this.setChangeTracker(this.changeTracker().emailAddressChangedOn(asOfDate));
        }
    }

    /**
     * 改变名字
     * @param aFirstName	  名字
     * @param aLastName		  姓氏
     * @param asOfDate		  截至日期
     */
    public void changeName(String aFirstName, String aLastName, Date asOfDate) {
        // 如果追踪器的可以改变名字，则改变；否则不改变
        if (this.changeTracker().canChangeName(asOfDate)) {
            // 设置名字
            this.setFirstName(aFirstName);
            // 设置姓氏
            this.setLastName(aLastName);
            // 由截至日期，重置追踪器的名字
            this.setChangeTracker(this.changeTracker().nameChangedOn(asOfDate));
        }
    }

    /**
     * 禁用
     * @param asOfDate 截至日期
     */
    public void disable(Date asOfDate) {
        // 如果追踪器的可以切换启用，则改变；否则不改变
        if (this.changeTracker().canToggleEnabling(asOfDate)) {
            // 设置已启用为假（意为禁用）
            this.setEnabled(false);
            // 由截至日期，重置追踪器的启用
            this.setChangeTracker(this.changeTracker().enablingOn(asOfDate));
        }
    }

    /**
     * 启用
     * @param asOfDate 截至日期
     */
    public void enable(Date asOfDate) {
        // 如果追踪器的可以切换启用，则改变；否则不改变
        if (this.changeTracker().canToggleEnabling(asOfDate)) {
            // 设置已启用为真（意为启用）
            this.setEnabled(true);
            // 由截至日期，重置追踪器的启用
            this.setChangeTracker(this.changeTracker().enablingOn(asOfDate));
        }
    }

    /**
     * 获取邮件地址
     * @return 返回邮件地址
     */
    public String emailAddress() {
        return this.emailAddress;
    }

    /**
     * 是否启用
     * @return	返回是否启用
     */
    public boolean isEnabled() {
        return this.enabled;
    }

    /**
     * 获取名字
     * @return	返回名字
     */
    public String firstName() {
        return this.firstName;
    }

    /**
     * 获取姓氏
     * @return 返回姓氏
     */
    public String lastName() {
        return this.lastName;
    }

    /**
     * 获取租户编号
     * @return	返回租户编号
     */
    public TenantId tenantId() {
        return this.tenantId;
    }

    /**
     * 获取用户名
     * @return	返回用户名
     */
    public String username() {
        return this.username;
    }

    /**
     * 受保护的：由以下参数构造成员
     * @param aTenantId			租户编号
     * @param aUsername			用户名
     * @param aFirstName		名字
     * @param aLastName			姓名
     * @param anEmailAddress	邮件地址
     */
    protected Member(
            TenantId aTenantId,
            String aUsername,
            String aFirstName,
            String aLastName,
            String anEmailAddress) {
        // 调用默认构造器
        this();

        // 设置邮件地址
        this.setEmailAddress(anEmailAddress);

        // 设置名字
        this.setFirstName(aFirstName);

        // 设置姓氏
        this.setLastName(aLastName);

        // 设置租户编号
        this.setTenantId(aTenantId);

        // 设置用户名
        this.setUsername(aUsername);
    }

    /**
     * 受保护的默认成员构造器
     */
    protected Member() {
        // 调用父类的默认构造器
        super();
    }

    /**
     * 获取成员改变追踪器
     * @return 返回成员改变追踪器
     */
    private MemberChangeTracker changeTracker() {
        return this.changeTracker;
    }

    /**
     * 设置成员
     * @param aChangeTracker
     */
    private void setChangeTracker(MemberChangeTracker aChangeTracker) {
        this.changeTracker = aChangeTracker;
    }

    /**
     * 设置邮件地址
     * @param anEmailAddress
     */
    private void setEmailAddress(String anEmailAddress) {
        // 如果邮件地址有效，验证一下长度
        if (anEmailAddress != null) {
            this.assertArgumentLength(anEmailAddress, 100, "Email address must be 100 characters or less.");
        }

        this.emailAddress = anEmailAddress;
    }

    /**
     * 设置启用值
     * @param anEnabled 启用值
     */
    private void setEnabled(boolean anEnabled) {
        this.enabled = anEnabled;
    }

    /**
     * 设置名字
     * @param aFirstName 名字
     */
    private void setFirstName(String aFirstName) {
        // 如果名字有效，验证一下长度
        if (aFirstName != null) {
            this.assertArgumentLength(aFirstName, 50, "First name must be 50 characters or less.");
        }

        this.firstName = aFirstName;
    }

    /**
     * 设置姓氏
     * @param aLastName 姓氏
     */
    private void setLastName(String aLastName) {
        // 如果姓氏有效，验证一下长度
        if (aLastName != null) {
            this.assertArgumentLength(aLastName, 50, "Last name must be 50 characters or less.");
        }

        this.lastName = aLastName;
    }

    /**
     * 设置租户编号
     * @param aTenantId 租户编号
     */
    private void setTenantId(TenantId aTenantId) {
        // 做一下有效性验证
        this.assertArgumentNotNull(aTenantId, "The tenant id must be provided.");

        this.tenantId = aTenantId;
    }

    /**
     * 设置用户名
     * @param aUsername
     */
    private void setUsername(String aUsername) {
        // 不为空验证
        this.assertArgumentNotEmpty(aUsername, "The username must be provided.");
        // 长度验证
        this.assertArgumentLength(aUsername, 250, "The username must be 250 characters or less.");

        this.username = aUsername;
    }
}
